package com.zone.editor.task;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.zone.editor.BitmapUtil;
import com.zone.editor.BoxHelper;
import com.zone.editor.inter.DrawingView;
import com.zone.editor.inter.Editor;
import com.zone.editor.SaveSettings;
import com.zone.editor.inter.EditorView;
import com.zone.editor.inter.OnSaveBitmap;
import com.zone.editor.photoEditor.R;
import com.zone.sdk.isd.util.ISDUtil;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class SaverTask extends AsyncTask<String, String, SaverTask.SaveResult> {

    public static final String TAG = "SaverTask";
    private @NonNull
    SaveSettings mSaveSettings;
    private @Nullable
    Editor.OnSaveListener mOnSaveListener;
    private @Nullable
    OnSaveBitmap mOnSaveBitmap;
    private final EditorView editorView;
    private final BoxHelper mBoxHelper;
    private final DrawingView drawingView;


    public SaverTask(EditorView editorView, BoxHelper boxHelper) {
        this.editorView = editorView;
        drawingView = editorView.getDrawingView();
        mBoxHelper = boxHelper;
        mSaveSettings = new SaveSettings.Builder().build();
    }

    public void setOnSaveListener(@Nullable Editor.OnSaveListener onSaveListener) {
        this.mOnSaveListener = onSaveListener;
    }

    public void setOnSaveBitmap(@Nullable OnSaveBitmap onSaveBitmap) {
        mOnSaveBitmap = onSaveBitmap;
    }

    public void setSaveSettings(@NonNull SaveSettings saveSettings) {
        mSaveSettings = saveSettings;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mBoxHelper.clearHelperBox();
        drawingView.destroyDrawingCache();
    }

    @SuppressLint("MissingPermission")
    @Override
    protected SaveResult doInBackground(String... inputs) {
        // Create a media file name
        if (inputs.length == 0) {
            return saveImageAsBitmap();
        } else if (inputs.length == 1){
            return saveImageInFile(inputs[0]);
        } else {
            return saveIsdImageInFile(inputs[0]);
        }
    }

    private SaveResult saveImageAsBitmap() {
        if (editorView != null) {
            return new SaveResult(null, null, buildBitmap());
        } else {
            return new SaveResult(null, null, null);
        }
    }

    @NonNull
    private SaveResult saveIsdImageInFile(String mImagePath) {
        byte[] mImageSourcePlay;
        String mImagePathPlay = mImagePath+".bmp";
        mImagePath = mImagePath+".png";
        if (editorView != null && editorView.getTemplateBitmap() != null) {
            Bitmap capturedBitmap = buildBitmap();
            Bitmap template = editorView.getTemplateBitmap();
            int width = template.getWidth();
            int height = template.getHeight();
            mImageSourcePlay = ISDUtil.saveBitmap(editorView.getContext(), capturedBitmap, mImagePath, mImagePathPlay,  width, height, template);
            return new SaveResult(null, mImagePath, mImagePathPlay, null, mImageSourcePlay, width, height);
        }else {
            return new SaveResult(null, mImagePath, mImagePathPlay, null, null);
        }
    }

    @NonNull
    private SaveResult saveImageInFile(String mImagePath) {
        File file = new File(mImagePath);
        try {
            FileOutputStream out = new FileOutputStream(file);
            BufferedOutputStream bos = new BufferedOutputStream(out);
            if (editorView != null) {
                Bitmap capturedBitmap = buildBitmap();
                capturedBitmap.compress(mSaveSettings.getCompressFormat(), mSaveSettings.getCompressQuality(), out);
            }
            out.flush();
            bos.flush();
            out.close();
            bos.close();
            Log.d(TAG, "Filed Saved Successfully");
            return new SaveResult(null, mImagePath, null);
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "Failed to save File");
            return new SaveResult(e, mImagePath, null);
        }
    }

    private Bitmap buildBitmap() {
        return mSaveSettings.isTransparencyEnabled()
                ? captureView(editorView) : BitmapUtil.removeTransparency(captureView(editorView));
    }

    @Override
    protected void onPostExecute(SaveResult saveResult) {
        super.onPostExecute(saveResult);
        if (TextUtils.isEmpty(saveResult.mImagePath)) {
            handleBitmapCallback(saveResult);
        } else {
            handleFileCallback(saveResult);
        }

    }

    private void handleFileCallback(SaveResult saveResult) {
        Exception exception = saveResult.mException;
        if (exception == null) {
            //Clear all views if its enabled in save settings
            if (mSaveSettings.isClearViewsEnabled()) {
                mBoxHelper.clearAllViews(drawingView);
            }
            if (mOnSaveListener != null) {
                Editor.ImageResult result = new Editor.ImageResult();
                result.setHeight(saveResult.height);
                result.setWidth(saveResult.width);
                result.setmBitmap(saveResult.mBitmap);
                result.setmImagePath(saveResult.mImagePath);
                result.setmImagePathPlay(saveResult.mImagePathPlay);
                result.setmImageSourcePlay(saveResult.mImageSourcePlay);
                mOnSaveListener.onSuccess(result);
            }
        } else {
            if (mOnSaveListener != null) {
                mOnSaveListener.onFailure(exception);
            }
        }
        if (onTaskFinishListener != null){
            onTaskFinishListener.onFinish(false);
        }
    }

    private void handleBitmapCallback(SaveResult saveResult) {
        Bitmap bitmap = saveResult.mBitmap;
        if (bitmap != null) {
            if (mSaveSettings.isClearViewsEnabled()) {
                mBoxHelper.clearAllViews(drawingView);
            }
            if (mOnSaveBitmap != null) {
                mOnSaveBitmap.onBitmapReady(bitmap);
            }
        } else {
            if (mOnSaveBitmap != null) {
                mOnSaveBitmap.onFailure(new Exception("Failed to load the bitmap"));
            }
        }
        if (onTaskFinishListener != null){
            onTaskFinishListener.onFinish(true);
        }
    }

    public Bitmap captureView(EditorView editorView) {
//        Bitmap bitmap = Bitmap.createBitmap(
//                editorView.getWidth(),
//                editorView.getHeight(),
//                Bitmap.Config.ARGB_8888
//        );
        Bitmap  bitmap = Bitmap.createBitmap(
                BitmapFactory.decodeResource(editorView.getContext().getResources(), R.drawable.pic_transparent),
                0, 0, editorView.getWidth(), editorView.getHeight());
        Canvas canvas = new Canvas(bitmap);
        editorView.draw(canvas);
        return bitmap;
    }

    public void setOnTaskFinishListener(OnTaskFinishListener onTaskFinishListener) {
        this.onTaskFinishListener = onTaskFinishListener;
    }

    private OnTaskFinishListener onTaskFinishListener;



    public interface OnTaskFinishListener{
        void onFinish(boolean flag);
    }

    private Bitmap captureViewCustom(View view) {
        Bitmap bitmap = Bitmap.createBitmap(
                view.getWidth(),
                view.getHeight(),
                Bitmap.Config.ARGB_8888
        );
        Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);
        return bitmap;
    }

    public void saveBitmap() {
        execute();
    }

    public void saveFile(String imagePath) {
        execute(imagePath);
    }

    static class SaveResult {
        final Exception mException;
        final String mImagePath;
        final String mImagePathPlay;
        final byte[] mImageSourcePlay;
        final Bitmap mBitmap;
        int width;
        int height;

        public SaveResult(Exception exception, String imagePath, Bitmap bitmap) {
            this(exception, imagePath, null, bitmap, null);
        }

        public SaveResult(Exception exception, String imagePath, String mImagePathPlay, Bitmap bitmap, byte[] mImageSourcePlay) {
            mException = exception;
            mImagePath = imagePath;
            mBitmap = bitmap;
            this.mImagePathPlay = mImagePathPlay;
            this.mImageSourcePlay = mImageSourcePlay;
        }
        public SaveResult(Exception exception, String imagePath, String mImagePathPlay, Bitmap bitmap, byte[] mImageSourcePlay, int width, int height) {
            mException = exception;
            mImagePath = imagePath;
            mBitmap = bitmap;
            this.mImagePathPlay = mImagePathPlay;
            this.mImageSourcePlay = mImageSourcePlay;
            this.width = width;
            this.height = height;
        }
    }
}
